home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / powervww / pvhelp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-05  |  21.7 KB  |  917 lines

  1. //  ____________________________________________________
  2. // |                                                    |
  3. // |  Project:     POWER VIEW INTERFACE                 |
  4. // |  File:        PVHELP.CPP                           |
  5. // |  Compiler:    WPP386 (10.6)                        |
  6. // |                                                    |
  7. // |  Subject:     Help manager implementation          |
  8. // |                                                    |
  9. // |  Author:      Emil Dotchevski                      |
  10. // |____________________________________________________|
  11. //
  12. // E-mail: zajo@geocities.com
  13. // URL:    http://www.geocities.com/SiliconValley/Bay/3577
  14.  
  15. #ifndef NOHELP
  16.  
  17. #define uses_ctype
  18. #define uses_dos
  19. #define uses_fcntl
  20. #define uses_io
  21. #define uses_string
  22. #define uses_dc
  23. #define uses_dialog
  24. #define uses_ht
  25. #define uses_icons
  26. #define uses_list
  27. #define uses_stddlg
  28. #define uses_system
  29.  
  30. #include "PVuses.h"
  31.  
  32. #define MAX_BACK_TOPICS  0x20
  33. #define HLP_SIGNATURE    "\r\nPower View help file.\r\n\032"
  34. #define DONT_WRAP        '`'
  35. #define CR               '\r'
  36. #define VSCROLL_AHEAD    2
  37. #define HSCROLL_AHEAD    5
  38.  
  39. #define cmHLP_ON_HELP    cmUSER00
  40. #define cmHLP_INDEX      cmUSER01
  41. #define cmHLP_CONTENTS   cmUSER02
  42. #define cmHLP_CROSS_REF  cmUSER03
  43. #define cmHLP_BACK       cmUSER04
  44.  
  45. class Thelp: public Titem
  46. {
  47.   public:
  48.     Thscroll_bar *hbar;
  49.     Tvscroll_bar *vbar;
  50.     char *vbegprint_org;
  51.     uint vbeg_print;
  52.     uint hbeg_print;
  53.     uint rows_num;
  54.     uint cols_num;
  55.     uint cursor_x;
  56.     uint cursor_y;
  57.     char *cursor_org;
  58.     char *hilight;
  59.     char *help;
  60.     uint help_size;
  61.     uint help_len;
  62.     uint topics_num;
  63.     word *topics;
  64.     uint current_topic;
  65.     char *line_org;
  66.     uint line_org_num;
  67.     boolean wrapped;
  68.     char search[256];
  69.     Thelp( int _xl, int _yl );
  70.     virtual ~Thelp( void );
  71.     virtual void resize( int newxl, int newyl );
  72.     virtual void draw( void );
  73.     virtual void event_handler( Tevent &ev );
  74.     void go_forward( void );
  75.     void cross_reference( void );
  76.     void go_back( void );
  77.     void cursor_up( void );
  78.     void cursor_down( void );
  79.     void cursor_page_up( void );
  80.     void cursor_page_down( void );
  81.     void cursor_left( void );
  82.     void cursor_right( void );
  83.     void cursor_top( void );
  84.     void cursor_bottom( void );
  85.     void cursor_home( void );
  86.     void cursor_end( void );
  87.     void tab_topic( int direction );
  88.     void speed_search( char c );
  89.     char *get_line_org( uint i );
  90.     char *next_line_org( void );
  91.     void update( void );
  92.     void update_hilight( void );
  93.     void update_cursor_org( void );
  94.     void update_cursor_xy( void );
  95.     inline void read_help( unsigned long o, uint s );
  96.     void read_topic( uint ht );
  97.  
  98.     inline void set_cursor_org( char *p )
  99.     {
  100.       cursor_org = p;
  101.       while( *cursor_org == DONT_WRAP ) cursor_org++;
  102.     }
  103.  
  104.     inline void set_vbegprint_org( char *p )
  105.     {
  106.       vbegprint_org = p;
  107.       while( *vbegprint_org == DONT_WRAP ) vbegprint_org++;
  108.     }
  109. };
  110.  
  111. struct Tback_info
  112. {
  113.   uint topic_num;
  114.   uint hbeg_prn;
  115.   uint curs_org;
  116.   uint vbegprn_org;
  117. };
  118.  
  119. static Tback_info back_info[MAX_BACK_TOPICS];
  120. static uint back_info_ptr = 0;
  121. static char help_filename[_MAX_PATH];
  122.  
  123.  
  124. void set_help_filename( char *filename )
  125. {
  126.   strcpy( help_filename, filename );
  127. }
  128.  
  129. static Thelp *help_item;
  130.  
  131. boolean help_validator( uint stop_code )
  132. {
  133.   switch( stop_code )
  134.   {
  135.     case cmHLP_ON_HELP:
  136.       help_item->go_forward();
  137.       help_item->read_topic( htHELP_ON_HELP );
  138.       break;
  139.     case cmHLP_INDEX:
  140.       help_item->go_forward();
  141.       help_item->read_topic( htHELP_INDEX );
  142.       break;
  143.     case cmHLP_CONTENTS:
  144.       help_item->go_forward();
  145.       help_item->read_topic( htHELP_CONTENTS );
  146.       break;
  147.     case cmHLP_CROSS_REF:
  148.       help_item->cross_reference();
  149.       break;
  150.     case cmHLP_BACK:
  151.       help_item->go_back();
  152.       break;
  153.     default:
  154.       return 1;
  155.   }
  156.   help_item->resize( help_item->xl, help_item->yl );
  157.   return 0;
  158. }
  159.  
  160. static Tbutton *btn( char *t, uint cmd, uint sc )
  161. {
  162.   Tbutton *b;
  163.  
  164.   b = button( t, cmd );
  165.   b->shortcut = sc;
  166.   b->set_flags( ifSELECTABLE, 0 );
  167.   return b;
  168. }
  169.  
  170. void online_help( uint help_context )
  171. {
  172.   static int recurse=0;
  173.   uint t;
  174.   Tdialog *d;
  175.  
  176.   if( recurse ) return;
  177.   recurse++;
  178.   if( help_context )
  179.     t = help_context;
  180.   else
  181.     t = htHELP_CONTENTS;
  182.   help_item = NEW( Thelp( 50, 16 ) );
  183.   help_item->read_topic( t );
  184.   if( help_item->help == NULL )
  185.   {
  186.     DELETE( help_item );
  187.     _terror();
  188. #ifdef CYR
  189.     ok( "Å«¼«╣▓á ¡Ñ Ñ ¡á¼Ñ░Ñ¡á.\n\n┐ »░«óÑ░Ñ▓Ñ ñ὿ ▒║╣Ñ▒▓ó│óá ┤á⌐½ \"%s\".", help_filename );
  190. #else
  191.     ok( "Can not read help topic.\n\nPlease verify the file \"%s\" exist.", help_filename );
  192. #endif
  193.     recurse--;
  194.     return;
  195.   }
  196. #ifdef CYR
  197.   _phelp(); d = dialog( "Å«¼«╣" );
  198. #else
  199.   _phelp(); d = dialog( "Help" );
  200. #endif
  201.   d->set_flags( ifRESIZEABLE, 1 );
  202.   d->xl_min = 38;
  203.   d->yl_min = 14;
  204.   validator( help_validator );
  205.   hspaces( -1 );
  206. #ifdef CYR
  207.   btn( "|~Å░Ñ»░á▓¬á ", cmHLP_CROSS_REF, kENTER )->set_flags( bfDEFAULT, 1 );
  208.   btn( "  |~ìáºáñ   ", cmHLP_BACK,      kALT_F1 );
  209.   btn( "|~æ║ñ║░ªá¡¿Ñ", cmHLP_CONTENTS,  kCTRL_F1 );
  210.   btn( " |~Ǻí│╖¡¿¬ ", cmHLP_INDEX,     kSHIFT_F1 );
  211.   btn( "  Å«¼«╣   ", cmHLP_ON_HELP,   0 );
  212.   btn( " çá▓ó«░¿  ",   cmCANCEL,        kESC );
  213. #else
  214.   btn( "Cross |~ref", cmHLP_CROSS_REF, kENTER )->set_flags( bfDEFAULT, 1 );
  215.   btn( " Go |~back ", cmHLP_BACK,      kALT_F1 );
  216.   btn( "|~Contents ", cmHLP_CONTENTS,  kCTRL_F1 );
  217.   btn( "  |~Index  ", cmHLP_INDEX,     kSHIFT_F1 );
  218.   btn( "  Help   ", cmHLP_ON_HELP,   0 );
  219.   btn( " Cancel  ",   cmCANCEL,        kESC );
  220. #endif
  221.   nc(); vspaces( -1 ); hspace();
  222.   _stay(); put_item( help_item, help_item->xl + 1 + i_sb_up_len, help_item->yl + 1 );
  223.   run();
  224.   help_item->go_forward();
  225.   DELETE( help_item );
  226.   recurse--;
  227. }
  228.  
  229. // HELP ITEM
  230.  
  231. Thelp::Thelp( int _xl, int _yl ):
  232.   Titem( _xl, _yl )
  233. {
  234. #ifndef NOMOUSE
  235.   set_events_mask( evMOUSE_REP, 1 );
  236. #endif
  237.   vbar = NEW( Tvscroll_bar( yl, rows_num, vbeg_print ) );
  238.     vbar->set_flags( sfHANDLE_KEYBOARD+sfHIDEABLE, 0 );
  239.   hbar = NEW( Thscroll_bar( xl+1, cols_num, hbeg_print ) );
  240.     hbar->set_flags( sfHANDLE_KEYBOARD+sfHIDEABLE, 0 );
  241.   put_in( hbar, 0, yl );
  242.   put_in( vbar, xl + 1, 0 );
  243.   rows_num = 0;
  244.   cols_num = 0;
  245.   hilight = help = line_org = NULL;
  246.   line_org_num = 0;
  247.   wrapped = 0;
  248.   grow_mode = gmGROW_BOTH;
  249.   curs_type = 1;
  250. }
  251.  
  252. Thelp::~Thelp( void )
  253. {
  254.   if( help != NULL ) FREE( help );
  255.   help = NULL;
  256. }
  257.  
  258. void Thelp::resize( int newxl, int newyl )
  259. {
  260.   uint hlen, h_count, line_chars, l;
  261.   uint v_count;
  262.   char *i, *line_start, *wrap, *p, *n;
  263.   boolean wrap_fl, topic_fl;
  264.  
  265.   Titem::resize( newxl, newyl );
  266.   if( help == NULL ) return;
  267.   if( wrapped )
  268.   {
  269.     i = help;
  270.     for( hlen = 0; hlen < help_len; hlen++ )
  271.     {
  272.       if( *i == 0 )
  273.         switch( *( i + 1 ) )
  274.         {
  275.           case CR:
  276.             *i = CR; break;
  277.           case DONT_WRAP:
  278.             *i = DONT_WRAP; break;
  279.           default:
  280.             *i = ' ';
  281.         }
  282.       i++;
  283.     }
  284.   }
  285.   wrap = help;
  286.   v_count = h_count = 0;
  287.   topic_fl = 0;
  288.   while( ( wrap - help ) <= help_len )
  289.   {
  290.     i = line_start = wrap;
  291.     wrap_fl = 1;
  292.     if( *i == DONT_WRAP )
  293.       wrap_fl = 0,
  294.       i += 2,
  295.       wrap += 2,
  296.       line_start += 2;
  297.     line_chars = 0;
  298.     while( ( ( i - help ) < help_len ) && ( *i != CR ) &&
  299.            ( !wrap_fl || topic_fl || ( wrap == line_start ) || ( line_chars <= xl ) ) )
  300.     {
  301.       if( *i == '|' ) topic_fl = !topic_fl, line_chars -= 2;
  302.       if( ( *i == ' ' ) && !topic_fl ) wrap = i;
  303.       i++;
  304.       line_chars++;
  305.     }
  306.     if( ( *i == CR ) && ( !wrap_fl || ( line_chars <= xl ) ) ) wrap = i;
  307.     if( *wrap == '|' ) wrap = i;
  308.     *(wrap++) = 0;
  309.     if( *wrap == CR ) wrap++;
  310.     l = smart_len( line_start );
  311.     if( l > h_count ) h_count = l;
  312.     v_count++;
  313.   }
  314.   cols_num = h_count; rows_num = v_count;
  315.   update_cursor_xy();
  316.   p = get_line_org( vbeg_print );
  317.   while( p < vbegprint_org )
  318.   {
  319.     n = p;
  320.     p = next_line_org();
  321.     if( p == NULL )
  322.     {
  323.       p = n;
  324.       break;
  325.     }
  326.     vbeg_print++;
  327.   }
  328.   while( p > vbegprint_org )
  329.   {
  330.     vbeg_print--;
  331.     p = get_line_org( vbeg_print );
  332.   }
  333.   update_cursor_org();
  334.   wrapped = 1;
  335. }
  336.  
  337. void Thelp::draw( void )
  338. {
  339.   uint i;
  340.   char *p;
  341.  
  342.   if( help == NULL ) return;
  343.   p = get_line_org( vbeg_print );
  344.   set_vbegprint_org( p );
  345.   goto_xy( 0, 0 ); txtf( "|r%c |l%c", xl, yl );
  346.   i = 0;
  347.   while( ( i < yl ) && ( p != NULL ) )
  348.   {
  349.     goto_xy( -hbeg_print, i );
  350.     txt( p );
  351.     p = next_line_org();
  352.     i++;
  353.   }
  354.   curs_x = cursor_x - hbeg_print;
  355.   curs_y = cursor_y - vbeg_print;
  356. }
  357.  
  358. void Thelp::event_handler( Tevent &ev )
  359. {
  360.   char n;
  361.  
  362.   if( state( isACTIVE ) && ( help != NULL ) )
  363.   {
  364.     switch( ev.code )
  365.     {
  366. #ifndef NOMOUSE
  367.       boolean dirty, inside_x, inside_y;
  368.       uint i, ii;
  369.       uint j, jj;
  370.       case evMOUSE_DOWN:
  371.         if( ev.INSIDE )
  372.         {
  373.           ii = (uint)-1; jj = (uint)-1;
  374.           do
  375.           {
  376.             dirty = 0;
  377.             inside_x = ( ev.LOCAL_X >= 0 ) && ( ev.LOCAL_X < xl );
  378.             inside_y = ( ev.LOCAL_Y >= 0 ) && ( ev.LOCAL_Y < yl );
  379.             if( inside_x || ( ev.code == evMOUSE_REP ) )
  380.             {
  381.               if( ev.LOCAL_X >= 0 ) j = ev.LOCAL_X; else j = 0;
  382.               j = hbeg_print + j;
  383.               if( !inside_x )
  384.               {
  385.                 if( j > cursor_x ) cursor_right(); else cursor_left();
  386.                 j = cursor_x;
  387.               }
  388.               if( j >= cols_num ) j = cols_num - 1;
  389.             }
  390.             if( inside_y || ( ev.code == evMOUSE_REP ) )
  391.             {
  392.               if( ev.LOCAL_Y >= 0 ) i = ev.LOCAL_Y; else i = 0;
  393.               i = vbeg_print + i;
  394.               if( !inside_y )
  395.               {
  396.                 if( i > cursor_y ) cursor_down(); else cursor_up();
  397.                 i = cursor_y;
  398.               }
  399.               if( i >= rows_num ) i = rows_num - 1;
  400.             }
  401.             if( j != jj )
  402.             {
  403.               cursor_x = j;
  404.               dirty = 1;
  405.             }
  406.             if( i != ii )
  407.             {
  408.               cursor_y = i;
  409.               dirty = 1;
  410.             }
  411.             if( dirty )
  412.             {
  413.               update_cursor_org();
  414.               update();
  415.               if( ev.CLICKS )
  416.               {
  417.                 cross_reference();
  418.                 break;
  419.               }
  420.             }
  421.             ii = i; jj = j;
  422.           }
  423.           while( get_mouse( ev, evMOUSE_REP | evMOUSE_DRAG ) );
  424.           item_acted = this;
  425.           handled( ev );
  426.         }
  427.       break;
  428. #endif
  429.       case evKEY_PRESS:
  430.         if( state( isFOCUSED ) )
  431.         {
  432.           n = *search; *search = 0;
  433.           switch( ev.ASCII )
  434.           {
  435.             case kUP:
  436.               cursor_up(); break;
  437.             case kDOWN:
  438.               cursor_down(); break;
  439.             case kPG_UP:
  440.               cursor_page_up(); break;
  441.             case kPG_DN:
  442.               cursor_page_down(); break;
  443.             case kCTRL_HOME:
  444.               cursor_top(); break;
  445.             case kCTRL_END:
  446.               cursor_bottom(); break;
  447.             case kLEFT:
  448.               cursor_left(); break;
  449.             case kRIGHT:
  450.               cursor_right(); break;
  451.             case kHOME:
  452.               cursor_home(); break;
  453.             case kEND:
  454.               cursor_end(); break;
  455.             case kTAB:
  456.               tab_topic( 1 ); break;
  457.             case kSHIFT_TAB:
  458.               tab_topic( -1 ); break;
  459.             case kF1:
  460.               help_item->go_forward();
  461.               help_item->read_topic( htHELP_ON_HELP );
  462.               break;
  463.             default:
  464.               if( ( ( ev.ASCII < 0x0020 ) && ( ev.ASCII != kBS ) ) || ( ev.ASCII > 0x00BF ) )
  465.                 goto hot;
  466.               else
  467.               {
  468.                 *search = n;
  469.                 speed_search( (char) ev.ASCII );
  470.               }
  471.           }
  472.           handled( ev );
  473.         }
  474.     }
  475.   hot:
  476.     if( wrapped )
  477.     {
  478.       update_cursor_org();
  479.       update();
  480.     }
  481.     else
  482.       resize( xl, yl );
  483.     cstate( cmHLP_BACK, back_info_ptr != 0 );
  484.     cstate( cmHLP_ON_HELP, current_topic != htHELP_ON_HELP );
  485.     cstate( cmHLP_INDEX, current_topic != htHELP_INDEX );
  486.     cstate( cmHLP_CONTENTS, current_topic != htHELP_CONTENTS );
  487.     cstate( cmHLP_CROSS_REF, hilight != NULL );
  488.   }
  489.   Titem::event_handler( ev );
  490. }
  491.  
  492. void Thelp::cursor_up( void )
  493. {
  494.   cursor_up_left( cursor_y, vbeg_print, yl, VSCROLL_AHEAD );
  495. }
  496.  
  497. void Thelp::cursor_down( void )
  498. {
  499.   cursor_down_right( cursor_y, vbeg_print, yl, rows_num, VSCROLL_AHEAD );
  500. }
  501.  
  502. void Thelp::cursor_page_up( void )
  503. {
  504.   if( vbeg_print < yl )
  505.     cursor_top();
  506.   else
  507.   {
  508.     vbeg_print -= ( yl - 1 );
  509.     cursor_y -= ( yl - 1 );
  510.   }
  511. }
  512.  
  513. void Thelp::cursor_page_down( void )
  514. {
  515.   if( ( vbeg_print + yl) >= rows_num )
  516.     cursor_bottom();
  517.   else
  518.   {
  519.     vbeg_print += ( yl - 1 );
  520.     cursor_y += ( yl - 1 );
  521.   }
  522. }
  523.  
  524. void Thelp::cursor_left( void )
  525. {
  526.   cursor_up_left( cursor_x, hbeg_print, xl, HSCROLL_AHEAD );
  527. }
  528.  
  529. void Thelp::cursor_right( void )
  530. {
  531.   cursor_down_right( cursor_x, hbeg_print, xl, cols_num, HSCROLL_AHEAD );
  532. }
  533.  
  534. void Thelp::cursor_top( void )
  535. {
  536.   cursor_top_home( cursor_y, vbeg_print );
  537. }
  538.  
  539. void Thelp::cursor_bottom( void )
  540. {
  541.   cursor_bottom_end( cursor_y, vbeg_print, yl, rows_num );
  542. }
  543.  
  544. void Thelp::cursor_home( void )
  545. {
  546.   cursor_top_home( cursor_x, hbeg_print );
  547. }
  548.  
  549. void Thelp::cursor_end( void )
  550. {
  551.   char *p;
  552.  
  553.   p = get_line_org( cursor_y );
  554.   cursor_bottom_end( cursor_x, hbeg_print, xl, smart_len( p ) );
  555. }
  556.  
  557. void Thelp::tab_topic( int direction )
  558. {
  559.   char *p, *help_end;
  560.  
  561.   p = cursor_org;
  562.   if( direction > 0 )
  563.   {
  564.     help_end = help + help_len - 1;
  565.     while( ( *( (word *) p ) != 0x627C ) && ( p < help_end ) )
  566.       p++;
  567.   }
  568.   else
  569.     while( ( *( (word *) p ) != 0x627C ) && ( p > help ) )
  570.       p--;
  571.   if( *( (word *) p ) == 0x627C )
  572.   {
  573.     *hilight = 'b';
  574.     hilight = ++p;
  575.     *hilight = 's';
  576.     set_cursor_org( ++p );
  577.     update_cursor_xy();
  578.     while( vbeg_print + yl <= cursor_y )
  579.       vbeg_print++;
  580.     while( vbeg_print > cursor_y )
  581.       vbeg_print--;
  582.   }
  583. }
  584.  
  585. void Thelp::speed_search( char c )
  586. {
  587.   char s[256], *i, *j, *p;
  588.   char n;
  589.   uint hbp, vbp, cx, cy, xx, yy;
  590.   word saved;
  591.  
  592.   if( !topics_num ) return;
  593.   cx = cursor_x; cy = cursor_y;
  594.   hbp = hbeg_print; vbp = vbeg_print;
  595.   c = toupper( c );
  596. #ifdef CYR
  597.   c = cyr_toupper( c );
  598. #endif
  599.   p = strchr( search, 0 ) - 1;
  600.   saved = (word) *p;
  601.   if( c != (char) kBS )
  602.     *( (word *) ( p + 1 ) ) = c;
  603.   else
  604.     if( *search ) *p = 0;
  605.   set_cursor_org( help );
  606.   vbeg_print = hbeg_print = cursor_y = cursor_x = 0;
  607.   update_cursor_xy();
  608.   if( *search == 0 ) return;
  609.   do
  610.   {
  611.     n = 1;
  612.     xx = cursor_x; yy = cursor_y;
  613.     tab_topic( 1 );
  614.     if( ( cursor_y == yy ) && ( cursor_x == xx ) )
  615.     {
  616.       cursor_x = cx; cursor_y = cy;
  617.       hbeg_print = hbp; vbeg_print = vbp;
  618.       *( (word *) p ) = saved;
  619.       return;
  620.     }
  621.     i = hilight + 1;
  622.     while( *i == ' ' )
  623.       i++, n++;
  624.     j = s;
  625.     while( *i != '|' )
  626.       *(j++) = *(i++);
  627.     *( s + strlen( search ) ) = 0;
  628. #ifdef CYR
  629.     cyr_strupr( s );
  630. #endif
  631.     strupr( s );
  632.   }
  633.   while( strcmp( s, search ) );
  634.   n += strlen( search );
  635.   while( --n )
  636.     cursor_right();
  637.   update_cursor_org();
  638.   if( hilight == NULL ) cursor_left();
  639. }
  640.  
  641. void Thelp::cross_reference( void )
  642. {
  643.   char *s, *i, *j;
  644.   uint n;
  645.  
  646.   if( ( help == NULL ) || ( hilight == NULL ) ) return;
  647.   n = 0;
  648.   s = get_line_org( 0 );
  649.   i = strstr( s, "|b" );
  650.   j = strstr( s, "|s" );
  651.   while( j == NULL )
  652.   {
  653.     while( i != NULL )
  654.     {
  655.       n++;
  656.       *i = ' ';
  657.       i = strstr( s, "|b" );
  658.     }
  659.     s = next_line_org();
  660.     i = strstr( s, "|b" );
  661.     j = strstr( s, "|s" );
  662.   }
  663.   n++;
  664.   i = strstr( s, "|t" );
  665.   while( i < j )
  666.   {
  667.     *i = ' ';
  668.     i = strstr( s, "|t" );
  669.     n++;
  670.   }
  671.   go_forward();
  672.   read_topic( topics[topics_num - n] );
  673. }
  674.  
  675. char *Thelp::get_line_org( uint i )
  676. {
  677.   if( i >= rows_num ) return NULL;
  678.   line_org = help;
  679.   line_org_num = 0;
  680.   while( line_org_num < i )
  681.   {
  682.     line_org = strchr( line_org, 0 ) + 1;
  683.     line_org_num++;
  684.   }
  685.   while( ( *line_org == DONT_WRAP ) || ( *line_org == CR ) )
  686.     line_org++;
  687.   return line_org;
  688. }
  689.  
  690. char *Thelp::next_line_org( void )
  691. {
  692.   if( line_org_num >= ( rows_num - 1 ) ) return NULL;
  693.   line_org = strchr( line_org, 0 ) + 1;
  694.   while( ( *line_org == DONT_WRAP ) || ( *line_org == CR ) )
  695.     line_org++;
  696.   line_org_num++;
  697.   return line_org;
  698. }
  699.  
  700. void Thelp::go_forward()
  701. {
  702.   if( ( back_info_ptr ) && ( back_info[back_info_ptr - 1].topic_num == current_topic ) ) return;
  703.   back_info[back_info_ptr].topic_num = current_topic;
  704.   back_info[back_info_ptr].hbeg_prn = hbeg_print;
  705.   back_info[back_info_ptr].curs_org = cursor_org - help;
  706.   back_info[back_info_ptr].vbegprn_org = vbegprint_org - help;
  707.   if( ++back_info_ptr == MAX_BACK_TOPICS )
  708.   {
  709.     back_info_ptr--;
  710.     memmove( &back_info[0], &back_info[1], sizeof( back_info ) - sizeof( Tback_info ) );
  711.   }
  712. }
  713.  
  714. void Thelp::go_back( void )
  715. {
  716.   if( !back_info_ptr ) return;
  717.   read_topic( back_info[--back_info_ptr].topic_num );
  718.   hbeg_print = back_info[back_info_ptr].hbeg_prn;
  719.   cursor_org = help + back_info[back_info_ptr].curs_org;
  720.   vbegprint_org = help + back_info[back_info_ptr].vbegprn_org;
  721. }
  722.  
  723. void Thelp::update( void )
  724. {
  725.   static char *old_vbegprint_org = NULL;
  726.   static char *old_hilight = NULL;
  727.   static uint old_hbeg_print = (uint)-1;
  728.   static uint old_vbeg_print = (uint)-1;
  729.  
  730.   if( ( old_hbeg_print != hbeg_print ) ||
  731.       ( old_vbeg_print != vbeg_print ) ||
  732.       ( old_hilight != hilight ) ||
  733.       ( old_vbegprint_org != vbegprint_org ) )
  734.   {
  735.     old_hbeg_print = hbeg_print;
  736.     old_vbeg_print = vbeg_print;
  737.     old_hilight = hilight;
  738.     old_vbegprint_org = vbegprint_org;
  739.     redraw();
  740.   }
  741.   curs_x = cursor_x - hbeg_print;
  742.   curs_y = cursor_y - vbeg_print;
  743. }
  744.  
  745. void Thelp::update_hilight( void )
  746. {
  747.   char *t, *b;
  748.  
  749.   if( hilight != NULL ) *hilight = 'b';
  750.   hilight = NULL;
  751.   t = get_line_org( cursor_y );
  752.   while( t != NULL )
  753.   {
  754.     b = strstr( t, "|b" );
  755.     t = strstr( t, "|t" );
  756.     if( ( cursor_org < t ) && ( cursor_org >= b ) )
  757.     {
  758.       *(++b) = 's';
  759.       hilight = b;
  760.       break;
  761.     }
  762.     if( t != NULL ) t++;
  763.   }
  764. }
  765.  
  766. void Thelp::update_cursor_org( void )
  767. {
  768.   char *p;
  769.   uint l;
  770.  
  771.   if( help == NULL ) return;
  772.   p = get_line_org( cursor_y );
  773.   l = smart_len( p );
  774.   if( cursor_x <= l )
  775.     set_cursor_org( p + smart_index( p, cursor_x ) );
  776.   else
  777.   {
  778.     p = next_line_org();
  779.     if( p != NULL )
  780.       set_cursor_org( p );
  781.     else
  782.     {
  783.       p = get_line_org( rows_num );
  784.       set_cursor_org( p + smart_index( p, smart_len( p ) - 1 ) );
  785.     }
  786.   }
  787.   update_hilight();
  788. }
  789.  
  790. void Thelp::update_cursor_xy( void )
  791. {
  792.   char *p, *n;
  793.   uint l;
  794.  
  795.   if( cursor_y >= rows_num ) cursor_y = rows_num - 1;
  796.   p = get_line_org( cursor_y );
  797.   while( p < cursor_org )
  798.   {
  799.     n = p;
  800.     p = next_line_org();
  801.     if( p == NULL )
  802.     {
  803.       p = n;
  804.       break;
  805.     }
  806.     cursor_y++;
  807.   }
  808.   while( p > cursor_org )
  809.     p = get_line_org( --cursor_y );
  810.   cursor_x = ( cursor_org - p );
  811.   if( cursor_x )
  812.   {
  813.     l = smart_len( p ); if( cursor_x > l ) cursor_x = l;
  814.     while( ( p + smart_index( p, cursor_x ) ) > cursor_org )
  815.       cursor_x--;
  816.   }
  817.   update_hilight();
  818. }
  819.  
  820. inline void Thelp::read_help( unsigned long o, uint s )
  821. {
  822.   int handle;
  823.   unsigned num_read;
  824.   uint i, n;
  825.   word k;
  826.   char *h;
  827.  
  828.   if( help != NULL ) FREE( help );
  829.   help = NULL;
  830.   if( !o || !s || _dos_open( help_filename, O_RDONLY, &handle) ) return;
  831.   help_size = s + 2;
  832.   help = (char *) MALLOC( help_size );
  833.   help[help_size-1] = 0;
  834.   help[help_size-2] = 0;
  835.   lseek( handle, o, 0 );
  836.   if( _dos_read( handle, help, s, &num_read ) || ( num_read != s ) )
  837.   {
  838.     FREE( help );
  839.     help = NULL;
  840.   }
  841.   _dos_close( handle );
  842.   if( help == NULL ) return;
  843.   help_len = s;
  844.   h = help;
  845.   i = 0;
  846.   n = 0;
  847.   do
  848.   {
  849.     if( ( *h == '|' ) && ( *( h + 1 ) == 't' ) )
  850.     {
  851.       h += 2; i += 2;
  852.       help_len -= 2;
  853.       k = *( (word *) h );
  854.       n += 2;
  855.       memmove( h, h + 2, help_size - i - n );
  856.       *( (word *) ( help + help_size - n ) ) = k;
  857.     }
  858. #ifndef HGR
  859.     if( graph_flag )
  860. #endif
  861.     {
  862. #ifdef CYR
  863.       if( *h == '╧' ) *h = frame_standard[2]; else
  864.       if( *h == '╙' ) *h = frame_standard[3]; else
  865. #endif
  866.       if( *h == '┘' ) *h = frame_standard[8];
  867.     }
  868.     i++; h++;
  869.   }
  870.   while( i < help_len );
  871.   topics_num = n >> 1;
  872.   topics = (word *) ( help + help_size - n );
  873.   wrapped = 0;
  874.   cursor_x = 0;
  875.   cursor_y = 0;
  876.   set_cursor_org( help );
  877.   set_vbegprint_org( help );
  878.   hbeg_print = 0;
  879.   vbeg_print = 0;
  880.   hilight = NULL;
  881.   *search = 0;
  882. }
  883.  
  884. void Thelp::read_topic( uint ht )
  885. {
  886.   static char signature[] = HLP_SIGNATURE;
  887.   char buf[256];
  888.   int handle;
  889.   unsigned num_read;
  890.   boolean signature_ok, opened;
  891.   unsigned long o;
  892.   word s;
  893.  
  894.   if( !ht ) return;
  895.   o = 0; s = 0;
  896.   signature_ok = 0; opened = 0;
  897.   if( !_dos_open( help_filename, O_RDONLY, &handle ) )
  898.   {
  899.     opened = 1;
  900.     if( !_dos_read( handle, buf, sizeof( signature ) - 1, &num_read ) )
  901.     {
  902.       buf[sizeof( signature ) - 1] = 0;
  903.       signature_ok = ( strcmp( buf, signature ) == 0 );
  904.     }
  905.   }
  906.   if( !signature_ok ) goto xit;
  907.   lseek( handle, (ht - 1) * 6, 1 );
  908.   if( _dos_read( handle, &o, sizeof(o), &num_read ) || ( num_read < sizeof(o) ) ) goto xit;
  909.   if( _dos_read( handle, &s, sizeof(s), &num_read ) || ( num_read < sizeof(s) ) ) goto xit;
  910. xit:
  911.   current_topic = ht;
  912.   if( opened ) _dos_close( handle );
  913.   read_help( o, s );
  914. }
  915.  
  916. #endif //NOHELP
  917.